import os
import json
import yaml
import glob
import shutil
import typing
import logging
import datetime
import zipfile


def read_file(file_path: str, mode: str = 'r'):
    with open(file_path, mode) as file:
        return file.read()


def write_zip_file(archive_path: str, files_to_archive: typing.List[str]):
    with zipfile.ZipFile(archive_path, 'w') as zipf:
        for file_path in files_to_archive:
            zipf.write(file_path, arcname=file_path.split('/')[-1])


def read_zip_file(archive_path: str, extractall_path: str):
    with zipfile.ZipFile(archive_path, 'r') as zipf:
        zipf.extractall(archive_path)


def write_params_to_json(file_path: str, data):
    with open(file_path, 'w') as f:
        json.dump(data, f, indent=4)


def read_params_from_json(file_path: str,):
    if os.path.exists(file_path):
        with open(file_path, 'r') as f:
            return json.load(f)
    else:
        return {}


def load_config(config_path: str) -> typing.Dict[str, typing.Any]:
    with open(config_path, 'r', encoding='utf-8') as f:
        return yaml.safe_load(f)


def create_config_model(path, data):
    with open(path, 'w') as file:
        yaml.dump(data, file, sort_keys=False)


def train_time(start_time: datetime.datetime):
    end_time = datetime.now()
    delta = (end_time - start_time).total_seconds()
    return f"{start_time.strftime('%H:%M:%S')} / {end_time.strftime('%H:%M:%S')} / {int(delta // 60)} мин. {int(delta % 60)} сек."


def init_log(logger, logs_path):
    if not os.path.exists(logs_path):
        os.makedirs(logs_path)
    log_filename = os.path.join(
        logs_path, f'{datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%s")}.log')
    logging.basicConfig(level=logging.INFO)
    logger.addHandler(logging.FileHandler(log_filename))


def upload_dataset(
        model_dir: str, file, _types: typing.List[str] = ["train", "val"]):
    os.makedirs(f"{model_dir}/archive", exist_ok=True)
    with open(f"{model_dir}/archive/{file['name']}", 'wb') as f:
        f.write(file['file_obj'].read())
    with zipfile.ZipFile(f"{model_dir}/archive/{file['name']}", 'r') as zipf:
        zipf.extractall(f"{model_dir}/temp")
    types_and_category = [
        [_type, _dir, []] for _dir in os.listdir(
            f"{model_dir}/temp") if os.path.isdir(f"{model_dir}/temp/{_dir}")
        for _type in _types
    ]
    for file_path in glob.glob(f"{model_dir}/temp/**/*.*", recursive=True):
        for _type, category, count in types_and_category:
            if _type in file_path and category in file_path:
                file_name = file_path.split("/")[-1]
                if _types != category:
                    path = f"{model_dir}/{_type}/{category}"
                else:
                    path = f"{model_dir}/{_type}"
                os.makedirs(path, exist_ok=True)
                shutil.move(file_path, f"{path}/{file_name}")
                count.append(f"{path}/{file_name}")
    shutil.rmtree(f"{model_dir}/temp")
    return types_and_category
